﻿using System;
using System.Collections.Generic;
using System.Linq;
using Models;

namespace BLL
{
    public class UserService:BaseService
    {
        private string passwordFormat = "SHA1";
        private EncryptionServie _encryptionService;
        private string sinaCSMFUserPassword = "csmf0";
        private string sinaSaltKey = "12345";

        public UserService()
        {
            _encryptionService = new EncryptionServie();
        }

        public void ActiveUser(int userId, string userName, string email)
        {

            var query = from u in db.Users
                        where u.Id ==userId 
                        select u;

            var newUser = query.SingleOrDefault();
            if(newUser != null)
            {
                newUser.UserName = userName;
                newUser.PasswordFormatId = (int)PasswordFormat.Hashed;
                newUser.Email = email;
                var saltKey = sinaSaltKey;
                newUser.PasswordSalt = saltKey;
                newUser.Password = _encryptionService.CreatePasswordHash(sinaCSMFUserPassword, saltKey, this.passwordFormat);
                newUser.Active = true;



                
                //delete old roles
                var rolesForUser = from r in db.User_Role_Mappings
                                   where r.User_Id == newUser.Id
                                   select r;

                foreach (var r in rolesForUser)
                {
                    db.User_Role_Mappings.DeleteOnSubmit(r);
                }


                var registerdRole= GetCustomerRoleBySystemName(SystemCustomerRoleNames.Registered);

                var userRoleMapping = new User_Role_Mapping()
                {
                    Role_Id = registerdRole.Id,
                    User_Id = newUser.Id
                };


                db.User_Role_Mappings.InsertOnSubmit(userRoleMapping);

                db.SubmitChanges();

            }

        }

        public UserInfo GetCustomerByUsername(string username)
        {
            if (string.IsNullOrEmpty(username))
                return null;

            var query = from c in db.Users
                        orderby c.Id
                        where c.UserName == username
                        select BuildUserInfo(c);
            var customer = query.FirstOrDefault();
            return customer;
        }

        public UserInfo GetCustomerByEmail(string email)
        {
            if (string.IsNullOrEmpty(email))
                return null;

            var query = from c in db.Users
                        orderby c.Id
                        where c.UserName == email
                        select BuildUserInfo(c);
            var customer = query.FirstOrDefault();
            return customer;

          
        }

        public RoleInfo GetCustomerRoleBySystemName(string roleName)
        {

            var query =
                from cr in db.Roles
                where cr.Name == roleName
                select new RoleInfo()
                           {
                               Id=cr.Id,
                               RoleName = cr.Name
                           };

            var role= query.SingleOrDefault();
            return role;

        }

        public void UpdateCustomer(UserInfo user)
        {
            if (user== null)
                throw new ArgumentNullException("user");


            var query = from u in db.Users
                        where u.Id == user.Id
                        select u;

            var foundUser = query.SingleOrDefault();
            if(foundUser != null)
            {
                foundUser.UserName = user.UserName;
                foundUser.PasswordFormatId = (int) user.PasswordFormat;
                foundUser.Email = user.Email;

                foundUser.PasswordSalt = user.PasswordSalt;
                foundUser.Password = user.Password;

                foundUser.Active = user.Active;
                foundUser.UserType = (int) user.UserType;
                foundUser.Intro = user.Intro;
                foundUser.UserLogo = user.UserLogo;


                //delete old roles
                var rolesForUser = from r in db.User_Role_Mappings
                            where r.User_Id == user.Id
                            select r;

                foreach(var r in rolesForUser)
                {
                    db.User_Role_Mappings.DeleteOnSubmit(r);
                }

                //insert new roles
                foreach(var r in user.Roles)
                {
                    var rolequery = from role in db.Roles
                                    where role.Name == r.RoleName
                                    select role.Id;

                    var userRoleMapping = new User_Role_Mapping()
                                              {
                                                  Role_Id = rolequery.SingleOrDefault(),
                                                  User_Id = user.Id
                                              };


                    db.User_Role_Mappings.InsertOnSubmit(userRoleMapping);
                }

                db.SubmitChanges();
            }
        }

        public UserInfo GetUserBySinaWeiboUserId(string id)
        {
            var query = from b in db.User_WeiboLogin_Bounds
                        where b.WeiboUserId == id.ToString()
                        select b;
            var bind = query.SingleOrDefault();
            if(bind!=null)
            {
                return this.GetUserById(bind.UserId);
            }
            return null;

        }

        public static User GetUserById(Db dataContent, int userId)
        {
            return (from u in dataContent.Users
                    where u.Id == userId
                    select u).FirstOrDefault();
        }

        private static UserInfo BuildUserInfo(User c)
        {
            var userInfo = new UserInfo()
                               {
                                   UserGuid = c.UserGuid,
                                   Active = c.Active,
                                   Deleted = c.Deleted,
                                   Email = c.Email,
                                   Id = c.Id,
                                   Password = c.Password,
                                   PasswordFormatId = c.PasswordFormatId,
                                   PasswordSalt = c.PasswordSalt,
                                   UserName = c.UserName,
                                   UserType = (UserType) c.UserType
                               };
            foreach (var r in c.User_Role_Mappings.Select(t => t.Role).ToList())
            {
                
                userInfo.Roles.Add(new RoleInfo(){Id = r.Id, RoleName = r.Name});
            }

            return userInfo;

        }

        private UserInfo GetUserById(int userId)
        {

            var query = from c in db.Users
                        where c.Id == userId
                        select BuildUserInfo(c);

            var customer = query.FirstOrDefault();
            return customer;
        }

        public UserInfo InsertGuestCustomer()
        {
            var customer = new UserInfo()
            {
                UserGuid = Guid.NewGuid(),
                Active = true,
                CreatedOn= DateTime.UtcNow,
            };

            //add to 'Guests' role
            var guestRole = GetCustomerRoleBySystemName(SystemCustomerRoleNames.Guests);
            if (guestRole == null)
                throw new Exception("'Guests' role could not be loaded");
            customer.Roles.Add(guestRole);

            var guest= new User();
            guest.UserGuid = customer.UserGuid;
            guest.Active = customer.Active;
            guest.CreatedOn = customer.CreatedOn;

            db.Users.InsertOnSubmit(guest);
            db.SubmitChanges();

            var userRoleMapping = new User_Role_Mapping()
            {
                Role_Id = guestRole.Id,
                User_Id = guest.Id
            };

            db.User_Role_Mappings.InsertOnSubmit(userRoleMapping);

            db.SubmitChanges();

            customer.Id = guest.Id;
            return customer;
        }

        public UserInfo GetUserByGuid(Guid userGuid)
        {
            if (userGuid == Guid.Empty)
                return null;

            var query = from c in db.Users
                        where c.UserGuid == userGuid
                        select BuildUserInfo(c);
            var customer = query.FirstOrDefault();
            return customer;
        }

        public UserInfo GetUserByName(string userName)
        {
            if (userName == string.Empty)
                return null;

            var query = from c in db.Users
                        where c.UserName == userName
                        select BuildUserInfo(c);
            var customer = query.FirstOrDefault();
            return customer;
        }

        public void BindSinaUser(int userId, string weiboUserId)
        {
            var found = from uc in db.User_WeiboLogin_Bounds
                        where uc.UserId == userId && uc.WeiboUserId == weiboUserId
                        select uc;
            if (!found.Any())
            {
                var bind = new User_WeiboLogin_Bound()
                               {
                                   ConnectToLoginId = Guid.NewGuid().ToString(),
                                   UserId = userId,
                                   WeiboUserId = weiboUserId
                               };

                db.User_WeiboLogin_Bounds.InsertOnSubmit(bind);
                db.SubmitChanges();
            }
        }

        public List<UserInfo> GetAllUsersForAdmin(bool isDeleted)
        {
            return (from c in db.Users
                    where c.Deleted == isDeleted
                    orderby c.Id descending
                    select BuildUserInfo(c)).ToList();
        }

        public void DeleteUserById(int userId)
        {
            var user = (from u in db.Users
                           where  u.Id == userId
                           select u).FirstOrDefault();

            if (user != null)
            {
                user.Deleted = true;
                db.SubmitChanges();
            }
        }

        public void RestoreUserById(int userId)
        {
            var user = (from u in db.Users
                        where u.Id == userId
                        select u).FirstOrDefault();

            if (user != null)
            {
                user.Deleted = false;
                db.SubmitChanges();
            }
        }

        public void UpdateUserLogo(int userId, string logoUrl)
        {
            var user = (from u in db.Users
                        where u.Id == userId
                        select u).FirstOrDefault();
            if (user != null)
            {
                user.UserLogo= logoUrl;
                db.SubmitChanges();
            }

        }
    }
}